home *** CD-ROM | disk | FTP | other *** search
- #include "stdafx.h"
-
- #define MAX_TRIES 30
-
- class cOccupied : public cBox
- {
- public:
- cOccupied(cOccupied **list, int x1, int y1, int x2, int y2, cProperties *p);
-
- static int jumpable(int x, int y, cProperties *p);
- static int occupy(int x, int y, cProperties *p);
-
- cProperties *what;
- };
-
- static cOccupied *game_occ = 0, *back_occ = 0;
-
- cOccupied::cOccupied(cOccupied **list, int _x1, int _y1, int _x2, int _y2, cProperties *p)
- {
- add((cList **)list);
-
- x1 = _x1, y1 = _y1, x2 = _x2, y2 = _y2;
-
- what = p;
- }
-
- int cOccupied::jumpable(int x, int y, cProperties *p)
- {
- ASSERT (p->objtype != 0);
-
- // Get list to check with
-
- cOccupied *list = *p->objtype->surface == game_surface? game_occ : back_occ;
-
- // Force jumpable when list is empty
-
- if (list == 0)
- return TRUE;
-
- // Get coordinates of bounding box
-
- int x1 = x + p->bbox.x1,
- y1 = y - p->bbox.y1,
- x2 = x + p->bbox.x2;
-
- // Check if any other platform is jumpable from this platform
-
- for (cOccupied *o = list; o != 0; o = (cOccupied *)o->next)
- {
- if (y1 == o->y1 && o->x1 - x2 <= LEVEL_HJUMP && x1 - o->x2 <= LEVEL_HJUMP)
- return TRUE;
-
- if (abs(y1 - o->y1) <= LEVEL_VJUMP && o->x1 - x2 <= LEVEL_HJUMP / 2 && x1 - o->x2 <= LEVEL_HJUMP / 2)
- return TRUE;
- }
-
- // None found
-
- return FALSE;
- }
-
- int cOccupied::occupy(int x, int y, cProperties *p)
- {
- ASSERT (p->objtype != 0);
-
- cOccupied **list = *p->objtype->surface == game_surface? &game_occ : &back_occ;
-
- int x1 = x + p->bbox.x1,
- y1 = y - p->bbox.y1,
- x2 = x + p->bbox.x2,
- y2 = y - p->bbox.y2;
-
- // If not forced to occupy check if there is another object in the list
- // occupying the same space
-
- if (p->no_overlap)
- for (cOccupied *o = *list; o != 0; o = (cOccupied *)o->next)
- if (x1 < o->x2 && o->x1 < x2 && y2 < o->y1 && o->y2 < y1)
- return FALSE;
-
- // Add to list
-
- new cOccupied(list, x1, y1, x2, y2, p);
-
- // Create real object
-
- cObjectTypes::make(x, y, p, TRUE);
-
- return TRUE;
- }
-
- static int determine_number(int r)
- {
- // This is assumed now
-
- ASSERT (r >= 0 && r <= 300);
-
- // Return number of things to create on this level
-
- if (r < 100)
- return rnd(100) < r? 1 : 0;
- else
- return (3 * r / 4 + rnd(r / 2) + 50) / 100;
- }
-
- static void make_platforms()
- {
- // Create random list
-
- cRandomList platforms(PLACEMENT_PLATFORM);
-
- if (platforms.is_empty() || random_placement_platform <= 0)
- {
- info("Warning: No platforms created!");
- return;
- }
-
- // Variable to indicate impossible jump
-
- int jumpable_warning = FALSE;
-
- // Loop through all levels
-
- for (int l = LEVEL_VJUMP; l < LEVEL_SIZE; l += LEVEL_VJUMP)
- {
- // Determine number of platforms to add
-
- int n = determine_number(random_placement_platform);
-
- // Case no platforms on this level
-
- if (n <= 0)
- {
- if (random_placement_platform >= 100)
- n = 1;
- else
- jumpable_warning = TRUE;
- }
-
- // Create platforms
-
- while (n > 0)
- {
- // Get random object
-
- cProperties *p = platforms.get_weighted_random();
-
- // Try to add this platform
-
- for (int tries = 0; tries < 2 * MAX_TRIES; tries++)
- {
- int x = -p->bbox.x1 + GAME_EDGE + rnd(GAME_DX - 2 * GAME_EDGE - (p->bbox.x2 - p->bbox.x1)),
- y = l + p->bbox.y1;
-
- if ((tries >= MAX_TRIES || cOccupied::jumpable(x, y, p)) && cOccupied::occupy(x, y, p))
- break;
- }
-
- n--;
- }
- }
-
- if (jumpable_warning)
- info("Warning: Level contains impossible jumps!");
- }
-
- static void make_on_platform()
- {
- cRandomList on_platform(PLACEMENT_ON_PLATFORM);
-
- if (on_platform.is_empty() || random_placement_on <= 0)
- return;
-
- for (cOccupied *o = game_occ; o != 0; o = (cOccupied *)o->next)
- if (o->what->placement == PLACEMENT_PLATFORM)
- for (int n = determine_number(random_placement_on); n > 0; n--)
- {
- cProperties *p = on_platform.get_weighted_random();
-
- if (p->bbox.x2 - p->bbox.x1 >= o->x2 - o->x1
- || o->y2 < GAME_DY
- || o->y1 - p->bbox.y1 > LEVEL_SIZE)
- continue;
-
- for (int tries = 0; tries < MAX_TRIES; tries++)
- {
- int x = o->x1 - p->bbox.x1 + rnd(o->x2 - o->x1 - (p->bbox.x2 - p->bbox.x1)),
- y = o->y1 + p->bbox.y2;
-
- if (cOccupied::occupy(x, y, p))
- break;
- }
- }
- }
-
- static void make_between_platforms()
- {
- }
-
- static void make_under_platform()
- {
- cRandomList under_platform(PLACEMENT_UNDER_PLATFORM);
-
- if (under_platform.is_empty() || random_placement_under <= 0)
- return;
-
- for (cOccupied *o = game_occ; o != 0; o = (cOccupied *)o->next)
- if (o->what->placement == PLACEMENT_PLATFORM)
- for (int n = determine_number(random_placement_under); n > 0; n--)
- {
- cProperties *p = under_platform.get_weighted_random();
-
- if (p->bbox.x2 - p->bbox.x1 >= o->x2 - o->x1
- || o->y2 < GAME_DY
- || o->y1 - p->bbox.y1 > LEVEL_SIZE)
- continue;
-
- for (int tries = 0; tries < MAX_TRIES; tries++)
- {
- int x = o->x1 - p->bbox.x1 + rnd(o->x2 - o->x1 - (p->bbox.x2 - p->bbox.x1)),
- y = o->y2 + p->bbox.y1;
-
- if (cOccupied::occupy(x, y, p))
- break;
- }
- }
- }
-
- static void make_any()
- {
- cRandomList any(PLACEMENT_ANY);
-
- if (any.is_empty() || random_placement_any <= 0)
- return;
-
- for (int n = LEVEL_VLEVELS * random_placement_any / 100; n > 0; n--)
- {
- cProperties *p = any.get_weighted_random();
-
- for (int tries = 0; tries < LEVEL_VLEVELS; tries++)
- {
- int x = -p->bbox.x1 + GAME_EDGE + rnd(GAME_DX - 2 * GAME_EDGE - (p->bbox.x2 - p->bbox.x1)),
- y = GAME_DY + p->bbox.y2 + rnd((*p->objtype->surface)->total_h - GAME_DY - (p->bbox.y2 - p->bbox.y1));
-
- if (cOccupied::occupy(x, y, p))
- break;
- }
- }
- }
-
- void make_level()
- {
- // First create platforms and stuff between platforms
-
- make_platforms();
- make_between_platforms();
-
- // Then create rest of shit
-
- make_on_platform();
- make_under_platform();
- make_any();
-
- // Remove occupied lists
-
- back_occ->delete_list();
- game_occ->delete_list();
-
- // Create editables
-
- cEditable::make_editables();
- }
-